import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Vector;

public class SegmentList 
{
	private Vector<Segment> segmentList;
	private Vector<Integer> toRemoveList;
	private SegmentPiece[][] allPieces;
	private boolean[][] binaryImage;
	private int imageWidth;
	private int imageHeight;
	
	public boolean[][] getBinaryImage() 
	{
		return binaryImage;
	}
	
	
	
	public Vector<Segment> getSegmentList() 
	{
		return segmentList;
	}



	public SegmentList(boolean[][] pixels, int w, int h)
	{
		imageWidth = w;
		imageHeight = h;
		binaryImage = pixels;
		allPieces = new SegmentPiece[w][h];
		
		/*set all id of pieces --> -1*/
		for (int y = 0; y < imageHeight; ++y) 
            for (int x = 0; x < imageWidth; ++x)
                allPieces[x][y] = new SegmentPiece(x, y, -1);
		
		segmentList = new Vector<Segment>();
		toRemoveList = new Vector<Integer>();
	}
	
	public void addSegment(Segment s)
	{
		segmentList.add(s);
	}
	
	public int getListSize()
	{
		return segmentList.size();
	}
	
	public void doSegmentation()
	{
		Log.d("SegmentList", "Starting segmentation!");
        
        int segId = -1;
        for (int y = 0; y < imageHeight; ++y) 
            for (int x = 0; x < imageWidth; ++x)  
            	/*take into account only white pixel which can be letters*/
            	if (binaryImage[x][y]) 
            	{ 
                    SegmentPiece sp = new SegmentPiece(x, y, -1);
                    if (x >= 1 && allPieces[x - 1][y].sId >= 0) 
                    {                        
                        if (y >= 1 && allPieces[x][y - 1].sId >= 0
                                && allPieces[x][y - 1].sId != allPieces[x - 1][y].sId) 
                        {
                            int upId = allPieces[x][y - 1].sId;	//up segment
                            int leftId = allPieces[x - 1][y].sId;  //left segment
                            int addId = Math.min(upId, leftId);
                            int removeId = Math.max(upId, leftId);
                            sp.sId = addId;
                            Segment toAddSeg = segmentList.elementAt(addId);
                            toAddSeg.addItem(sp); // add this pixel to upper segment
                            Segment toRemoveSeg = segmentList.elementAt(removeId);
                            for (int i = 0; i < toRemoveSeg.getPixels().size(); ++i) 
                            {
                                SegmentPiece sp2 = toRemoveSeg.getPixels().elementAt(i);
                                // for each pixel in left segment move it to upper segment
                                sp2.sId = sp.sId;
                                allPieces[sp2.x][sp2.y].sId = sp.sId;
                                toAddSeg.addItem(sp2);
                            }
                            toRemoveList.add(new Integer(removeId));
                            
                        } 
                        else 
                        {
                            sp.sId = allPieces[x - 1][y].sId;
                            segmentList.elementAt(sp.sId).addItem(sp);// add this pixel to segment
                        }
                    } 
                    else if (y >= 1 && allPieces[x][y - 1].sId >= 0) 
                    {
                        // upper pixel is already in segment so this one should belong to that segment too
                        sp.sId = allPieces[x][y - 1].sId;
                        segmentList.elementAt(sp.sId).addItem(sp);// add this pixel to segment
                    } 
                    else 
                    {
                        ++segId;
                        Segment segment = new Segment(segId);
                        sp.sId = segId;
                        segment.addItem(sp);
                        segmentList.add(segment);
                    }
                    allPieces[x][y] = sp;
                }

        // clear unused segments
        Collections.sort(toRemoveList);
        for (int i = 0; i < toRemoveList.size(); ++i) 
        	segmentList.remove(toRemoveList.elementAt(i) - i);                
    
		Log.d("SegmentList", "Ending segmentation!");
	}
	
	public void removeSmallSegments(int minValue)
	{
		Log.d("SegmentList", "Removing small segments!");
		Vector<Integer> ids = new Vector<Integer>();
        for (Iterator<Segment> iterator = segmentList.iterator(); iterator.hasNext();) 
        {
            Segment segment = iterator.next();
            if (segment.getSize() < minValue) 
                ids.add(new Integer(segment.getId()));            
        }
        
        for (Iterator<Integer> iterator = ids.iterator(); iterator.hasNext();) 
            removeSegment(iterator.next().intValue());      
        
        Log.d("SegmentList", "Finished removing start segment!");
        Log.d("SegmentList", "Number of segments: "+getListSize());
	}
	
	private void removeSegment(int id)
	{
		for (Iterator<Segment> it = segmentList.iterator(); it.hasNext();) 
		{
            Segment segment = it.next();
            if (segment.getId() == id) 
            {
                Vector<SegmentPiece> px = segment.getPixels();
                for (Iterator<SegmentPiece> iterator2 = px.iterator(); iterator2.hasNext();) 
                {
                	SegmentPiece coord = iterator2.next();
                    binaryImage[coord.x][coord.y] = false; // remove pixel from source bitmap
                }
                it.remove();
                break;
            }
        }		
	}
}
